package com.cskaoyan.order.service.remote;

import com.cskaoyan.mall.commons.exception.BizException;
import com.cskaoyan.mall.commons.exception.ExceptionProcessorUtils;
import com.cskaoyan.mall.order.api.PayOrderService;
import com.cskaoyan.mall.order.constant.OrderRetCode;
import com.cskaoyan.mall.order.dto.PayOrderSuccessRequest;
import com.cskaoyan.mall.order.dto.PayOrderSuccessResponse;
import com.cskaoyan.order.constant.OrderConstants;
import com.cskaoyan.order.dal.entitys.Order;
import com.cskaoyan.order.dal.entitys.OrderItem;
import com.cskaoyan.order.dal.entitys.Stock;
import com.cskaoyan.order.dal.persistence.OrderItemMapper;
import com.cskaoyan.order.dal.persistence.OrderMapper;
import com.cskaoyan.order.dal.persistence.StockMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author LY
 * @since 2022/06/22 16:36
 */
@Transactional
@Slf4j
@RestController
public class PayOrderServiceImpl implements PayOrderService {

    @Autowired
    OrderMapper orderMapper;

    @Autowired
    OrderItemMapper orderItemMapper;

    @Autowired
    StockMapper stockMapper;


    /**
     *  支付成功时，更新订单状态，更新锁定库存
     * @param request
     * @return
     */
    @Override
    public PayOrderSuccessResponse payOrderSuccess(PayOrderSuccessRequest request) {
        PayOrderSuccessResponse response = new PayOrderSuccessResponse();
        try {
            request.requestCheck();

            // 更新订单状态为ORDER_STATUS_PAYED=1
            String orderId = request.getOrderId();
            Order order = new Order();
            order.setOrderId(orderId);
            order.setStatus(OrderConstants.ORDER_STATUS_PAYED);
            order.setUpdateTime(new Date());
            int affectedRows = orderMapper.updateByPrimaryKeySelective(order);
            if(affectedRows != 1){
                log.error("更新数据库订单状态失败！");
                throw new BizException("更新数据库订单状态失败！");
            }

            // 更新订单锁定库存
            boolean reduceStock = reduceStockCountByOrderId(orderId);
            if(!reduceStock){
                log.error("更新锁定库存失败！");
                throw new BizException("更新锁定库存失败！");
            }
            response.setCode(OrderRetCode.SUCCESS.getCode());
            response.setMsg(OrderRetCode.SUCCESS.getMessage());
        }catch (Exception e){
            log.error("PayOrderServiceImpl.payOrderSuccess Occur Exception :" + e);
            e.printStackTrace();
            ExceptionProcessorUtils.wrapperHandlerException(response, e);
        }

        return response;
    }

    /***
     * 支付成功，根据OrderId减少对应商品锁定库存
     * @param orderId
     * @return boolean
     * @author LY
     * @since 2022/06/21 22:10
     */
    public boolean reduceStockCountByOrderId(String orderId){

        try {
            // 查询订单商品详细信息
            List<OrderItem> orderItems = orderItemMapper.queryByOrderId(orderId);

            // 获取订单商品Id
            List<Long> productIds = orderItems.stream().map(u -> u.getItemId()).sorted().collect(Collectors.toList());

            // 按照商品ID查询库存并锁定库存
            List<Stock> stockList = stockMapper.findStocksForUpdate(productIds);

            // 遍历订单商品，释放锁定库存
            for (OrderItem orderItem : orderItems) {
                Long productId = orderItem.getItemId();
                Integer productNum = orderItem.getNum();
                Stock stock = new Stock();
                stock.setItemId(productId);
                stock.setLockCount(-productNum);
                stock.setStockCount(0L);
                stockMapper.updateStock(stock);
            }
            return true;
        }catch (Exception e){
            log.error("OrderCoreServiceImpl.releaseLockCountByOrderId Occur Exception :" + e);
            e.printStackTrace();
            return false;
        }
    }
}
